package com.github.ykrank.alipayxposed.hook

import android.app.Activity
import android.content.Intent
import android.widget.ListView
import com.github.ykrank.alipayxposed.app.data.db.dbmodel.BillDetailsRawDao
import com.github.ykrank.alipayxposed.bridge.AppSettingContentValues
import com.github.ykrank.alipayxposed.bridge.BillH5ContentValues
import com.github.ykrank.androidtools.extension.toast
import com.github.ykrank.androidtools.service.Bill
import com.github.ykrank.androidtools.service.BillBody
import com.github.ykrank.androidtools.service.RestApiHelper
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.XposedHelpers
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.lang.ref.WeakReference
import java.util.concurrent.TimeUnit

object BillListHook {

    //libandroid-phone-wallet-billlist.so
    const val Cls_BillListAdapter = "com.alipay.mobile.bill.list.ui.adapter.BillListAdapter"
    const val Cls_BillListActivity = "com.alipay.mobile.bill.list.ui.BillListActivity" //实际上是BillListActivity_
    const val Cls_MainActivity = "com.eg.android.AlipayGphone.AlipayLogin"

    fun hookBillList(classLoader: ClassLoader) {
        var clazz = XposedHelpers.findClassIfExists(Cls_BillListActivity, classLoader)
        if (clazz == null) {
            XposedBridge.log("Could not find $Cls_BillListActivity")
            return
        }
        //adapter addAll
        XposedHelpers.findAndHookMethod(Cls_BillListAdapter, classLoader, "a",
                List::class.java, object : XC_MethodHook() {
            override fun beforeHookedMethod(param: MethodHookParam) {

                HookedApp.billListAdapter = WeakReference(param.thisObject)
                AppSettingContentValues.doIfEnable {
                    //                XposedBridge.log(Exception("BillListAdapter"))
//                XposedBridge.log("AddAll:${param.args[0]}")
                    var newBillList = ArrayList<Any>()
                    (param.args[0] as Collection<Any>).forEach {
                        if (HookedApp.billSingleListItems.contains(it).not()) {
                            newBillList.add(it)
                            HookedApp.billSingleListItems[it] = true
                        }
                    }

                    postAllBill(newBillList)
                }
            }
        })
        //onResume
        XposedHelpers.findAndHookMethod(Cls_BillListActivity, classLoader, "onResume",
                object : XC_MethodHook() {
                    override fun afterHookedMethod(param: MethodHookParam) {
                        XposedBridge.log("BillListActivity onResume")
                        HookedApp.billListActivityResume = true
                        HookedApp.billListActivityDestroyed = false
                        HookedApp.billListActivity = WeakReference(param.thisObject)
                        HookedApp.billListActivityClazz = param.thisObject.javaClass

                    }
                })
        XposedHelpers.findAndHookMethod(Cls_BillListActivity, classLoader, "onDestroy",
                object : XC_MethodHook() {
                    override fun afterHookedMethod(param: MethodHookParam) {
                        XposedBridge.log("BillListActivity onDestroy")
                        HookedApp.billListActivityDestroyed = true

                    }
                })
        XposedHelpers.findAndHookMethod(Cls_BillListActivity, classLoader, "onPause",
                object : XC_MethodHook() {
                    override fun afterHookedMethod(param: MethodHookParam) {
                        XposedBridge.log("BillListActivity onPause")
                        HookedApp.billListActivityResume = false
                    }
                })
    }

    lateinit var disposableUpload: Disposable

    private fun postAllBill(newBillList: ArrayList<Any>) {
        XposedBridge.log("newBillList size: ${newBillList.size}")
        var billList = extractBillInfo(newBillList)
        disposableUpload = RestApiHelper.create().uploadAlipayBillList(BillBody(billList))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    XposedBridge.log("resp-------:" + it.string())
                    disposableUpload.dispose()
                    afterUploadBillList(billList.size)
                }


    }

    private fun afterUploadBillList(size: Int) {
        XposedBridge.log("账单数据处理完成 共上传处理$size 条账单记录")
//        HookedApp.app?.toast("账单数据处理完成，即将返回上一页，10s后再次回到订单列表页")
//        XposedBridge.log("==========BB: ${FormatUtil.toJson(BillBody(billList))}")
        if (HookedApp.billSingleListItems.size > 0 && HookedApp.billListActivityResume) {

            var disposable = Observable
                    .just("")
                    .delay(3, TimeUnit.SECONDS)
                    .subscribeOn(Schedulers.computation())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe {
                        XposedBridge.log("Bill finish")
                        XposedHelpers.callMethod(HookedApp.billListActivity?.get(), "finish")
                        restartBiilistActivityAfter()
                    }
        }
    }

    private fun extractBillInfo(newBillList: ArrayList<Any>): ArrayList<Bill> {
        val billList = ArrayList<Bill>()
        if (newBillList.isEmpty()) {
            HookedApp.app?.toast("暂时没有新订单")
            return billList
        }
        var item = HookedApp.billSingleListItems.toList()[1].first
        XposedBridge.log("bill info : $item")
        item.javaClass.fields.forEach {
            XposedBridge.log("bill info : ${it.name}  ${it.type}")
        }
        newBillList.forEach {
            val fields = it.javaClass.fields
            fields[7].isAccessible = true
            fields[9].isAccessible = true
            fields[1].isAccessible = true
            var fee1 = fields[7].get(it)
            var memo1 = fields[9].get(it)
            var bizInNo1 = fields[1].get(it)
            if (fee1 != null) {
                val fee = (fee1 as String).substringAfter("+")
                val memo = (fields[9].get(it) as String).substringBefore("-")
                val bizInNo = fields[1].get(it) as String
                val bill = Bill(memo, fee, bizInNo)
                billList.add(bill)
            }
        }
        return billList
    }

    /**
     * 检测是否还有未处理的订单，若是则跳转，否则toast。
     */
    fun checkNextBill(listView: ListView) {
//        XposedBridge.log("listview:$listView")
//        goNextH5()?.let {
//            if (!it) {
//                if (HookedApp.billSingleListItems.size > 0 && HookedApp.billListActivityResume) {
//                    val disposable = Observable.just("")
//                            .delay(4, TimeUnit.SECONDS)
//                            .subscribe {
//                                //                            HookedApp.app.startActivity()
//                                val act = HookedApp.mainActivity?.get() as Activity
//                                act.startActivity(Intent(act, (HookedApp.billListActivity?.get() as Activity).javaClass))
//                            }
//                }

//
//            }
//        }
    }

    /**
     * 根据页面情况跳转到订单详情
     * @return 是否正确跳转。若null说明此时页面暂停状态
     */
    fun goNextH5(): Boolean? {
        if (HookedApp.billListActivityResume) {

            HookedApp.billSingleListItems.keys.find {
                !isItemParsed(it)
            }?.apply {
                return true
            }
            return false
        } else {
            XposedBridge.log("BillListActivity paused")
        }
        return null
    }

    /**
     * item是否已被处理过。即是否已解析保存在数据库中。
     * @param item SingleListItem
     */
    fun isItemParsed(item: Any): Boolean {
        val tradeNo = XposedHelpers.getObjectField(item, "bizInNo") as String?
        if (tradeNo.isNullOrEmpty()) {
            //首部月份Item
            val recordType = XposedHelpers.getObjectField(item, "recordType")
            if ("MONTH" != recordType?.toString()) {
                XposedBridge.log("Null tradeNo: $item")
            }
            return true
        }
        val uri = BillH5ContentValues.getItemUri(tradeNo!!)
        val cursor = HookedApp.app?.contentResolver?.query(uri, null, null, null, null)
        if (cursor != null && cursor.moveToFirst()) {
            val index = cursor.getColumnIndex(BillDetailsRawDao.Properties.RawHtml.columnName)
            val content = cursor.getString(index)
            if (content == null || !content.contains("加载中")) {
                cursor.close()
                return true
            }
        }
        cursor?.close()
        return false
    }

    /**
     * 跳转到订单详情界面。
     * @param item SingleListItem
     */
    fun goBillH5Page(item: Any) {
        val activity = HookedApp.billListActivity?.get()
        XposedBridge.log("goBillH5Page: $item")
        if (activity != null) {
            //item的点击事件，可以通过BillListAdapter中setOnClickListener找到
            //BillListAdapterListner.c(SingleListItem) 实际实现是BillListActivity
            try {
                XposedHelpers.callMethod(activity, "c", item)
            } catch (e: Throwable) {
                XposedBridge.log(e)
            }
        }
    }

    lateinit var disposable: Disposable
    fun restartBiilistActivityAfter() {
        disposable = Observable.just(0)
                .delay(10, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.computation())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (disposable.isDisposed.not())
                        disposable.dispose()
                    if (HookedApp.mainActivity?.get() != null
                            && HookedApp.billListActivityDestroyed) {
                        val mainActivity = HookedApp.mainActivity?.get() as Activity
                        val intent = Intent(mainActivity, HookedApp.billListActivityClazz)
                        XposedBridge.log("startActivity-->${mainActivity} --${HookedApp.billListActivityClazz}")
                        mainActivity.startActivity(intent)
                    }
                }


    }
}